package utils

import (
	"bufio"
	"errors"
	"fmt"
	log "github.com/sirupsen/logrus"
	"io"
	"os"
	"qabx.net/common"
	"qabx.net/safe-app-center/api/security_center_api"
	"qabx.net/safe-app-center/pkg/config/constants"
	"regexp"
	"strings"
)

// FeatureInit 初始化feature
func FeatureInit(featureFilePath, featureVersion string) bool {
	if featureVersion == "" {
		log.Error("initFeature version error, please input right version")
		return false
	}

	// 获取 Redis 最新版本号
	featureVersionKey := constants.REDIS_KEY_FEATURE_VERSION
	versions, err := TTLOperator.LRange(featureVersionKey, 0, 0)
	if err != nil {
		log.Errorf("Error getting TTL operator list: %v", err)
		return false
	}

	if len(versions) == 0 {
		if err = UpdateRedisFeature(featureFilePath, featureVersion); err != nil {
			log.Errorf("Error updating feature: %v", err)
			return false
		}
		log.Infof("feature update success, version: %v", featureVersion)
		return true
	}

	cmpResult := common.CompareGoVersions(featureVersion, versions[0])
	if cmpResult > 0 {
		if err = UpdateRedisFeature(featureFilePath, featureVersion); err != nil {
			log.Errorf("Error updating feature: %v", err)
			return false
		}
		log.Infof("feature update success, version: %v", featureVersion)
		return true
	} else {
		log.Errorf("feature update fail，新版本号需大于当前版本号, 当前版本: %v", versions[0])
		return false
	}
}

// UpdateRedisFeature 更新 redis feature数据
func UpdateRedisFeature(featureFilePath string, version string) error {
	// 打开文件
	file, err := os.Open(featureFilePath)
	if err != nil {
		log.Errorf("init redis feature error: %s", err.Error())
		return err
	}
	defer file.Close() // 关闭文本流

	reader := bufio.NewReader(file) // 读取文本数据

	featureKey := fmt.Sprintf("%s%v", constants.REDIS_KEY_FEATURE, version)
	featureVersionKey := fmt.Sprintf("%s", constants.REDIS_KEY_FEATURE_VERSION)

	compile := regexp.MustCompile("([0-9]{4,5}) ([\u4e00-\u9fa5a-zA-Z0-9]{1,}):(.{1,})")
	for {
		// 按行读取，使用 '\n' 作为分隔符
		line, err := reader.ReadString('\n')
		if err == io.EOF {
			break
		}
		if err != nil {
			log.Errorf("读取文件错误: %s", err.Error())
			return err
		}

		// 去除两端空格和 \r 字符
		line = strings.TrimSpace(strings.Replace(line, "\r", "", -1))
		if line == "" || strings.HasPrefix(line, "#") {
			// 空行或注释行跳过
			continue
		}

		featureOptions := compile.FindStringSubmatch(line)
		if len(featureOptions) != 4 {
			log.Errorf("init redis feature error: feature options len not equal 4,str is :%v", line)
			return err
		} else {
			//去除特殊字符串
			line = strings.Replace(line, "\r", "", 1)
			_, err = TTLOperator.LPushList(featureKey, line)
			if err != nil {
				log.Errorf("init redis feature error: LPushList error,str is :%v", line)
				return err
			}
		}
	}

	_, err = TTLOperator.LPushList(featureVersionKey, version)
	if err != nil {
		log.Errorf("init redis feature error: LPushList version error")
		return err
	}
	return nil
}

// GetFeatureContent 获取content值
func GetFeatureContent(version string) (list []string, err error) {
	featureFileKey := fmt.Sprintf("%s%v", constants.REDIS_KEY_FEATURE, version)
	list, err = TTLOperator.LRange(featureFileKey, 0, -1)
	if err != nil {
		log.Errorf("getFeatureContent error:%s", err.Error())
		return nil, err
	}
	if len(list) > 0 {
		return list, nil
	} else {
		return nil, nil
	}

}

// GetFeatureList 获取list值
func GetFeatureList(featureContent []string) (response *security_center_api.FeatureListResponse, err error) {
	responseList := make([]*security_center_api.Feature, 0)
	for _, v := range featureContent {
		compile := regexp.MustCompile("([0-9]{4,5}) ([\u4e00-\u9fa5a-zA-Z0-9]{1,}):(.{1,})")
		featureOptions := compile.FindStringSubmatch(v)
		if len(featureOptions) != 4 {
			log.Errorf("特征库格式有误" + v)
			return nil, errors.New("特征库格式有误")
		}
		featureOptions[3] = strings.Trim(strings.Replace(featureOptions[3], "[", "", 1), " ")
		featureOptions[3] = strings.Trim(strings.Replace(featureOptions[3], "]", "", 1), " ")
		featureItem := strings.Split(featureOptions[3], ",")
		id, _ := common.StringToInt64(featureOptions[1])

		for _, v := range featureItem {
			item := strings.Split(v, ";")
			if len(item) != 6 {

				log.Error("特征库格式有误")
				return nil, errors.New("特征库格式有误")
				//panic("特征格式有误" + v)
			}
			sPort, _ := common.StringToInt64(item[1])
			dPort, _ := common.StringToInt64(item[2])
			Feature := &security_center_api.Feature{
				Id:      id,
				Name:    featureOptions[2],
				Proto:   item[0],
				Sport:   sPort,
				Dport:   dPort,
				HostUrl: item[3],
				Request: item[4],
				Dict:    item[5],
			}
			responseList = append(responseList, Feature)
		}
	}

	response = &security_center_api.FeatureListResponse{
		List: responseList,
	}
	return response, nil
}
